#include "../fmt.h"

namespace sfc::fmt {

auto Style::xnew(Str s) -> Style {
  auto is_align = [](char c) { return c == '<' || c == '>' || c == '^' || c == '='; };
  auto is_sign = [](char c) { return c == '+' || c == '-' || c == ' '; };
  auto is_number = [](char c) { return '0' <= c && c <= '9'; };

  if (s.is_empty()) {
    return {};
  }

  auto x = Style{};
  auto i = 0u;
  auto n = u32(s.len());

  // [[fill]align]
  if (is_align(s[i + 1])) {
    x._fill = s[i++];
    x._align = s[i++];
  } else if (is_align(s[i + 0])) {
    x._align = s[i++];
  }

  // [sign]
  if (is_sign(s[i])) {
    x._sign = s[i++];
  }

  // [prefix]
  if (s[i] == '#') {
    x._prefix = s[i++];
  }

  // [width]
  for (; is_number(s[i]); i++) {
    x._width *= 10;
    x._width += u8(s[i] - '0');
  }

  // [.prec]
  if (s[i] == '.') {
    x._point = s[i++];

    for (; is_number(s[i]); i++) {
      x._prec *= 10;
      x._prec += u8(s[i] - '0');
    }
  }

  // [type]
  if (s[i] != '}' && s[i] != ':') {
    x._type = s[i++];
  }

  // [ext]
  if (s[i] == ':') {
    i++;

    for (; s[i] != '}'; i++) {
      if (x._desc_len >= sizeof(x._desc_arr)) break;
      x._desc_arr[x._desc_len++] = s[i];
    }
  }

  return x;
}

auto Pattern::next() -> Tuple<Str, Str> {
  const auto p = _0.find('{');
  const auto q = _0[{p || 0, _}].find('}');
  if (p.is_none() || q.is_none()) {
    return {mem::take(_0), {}};
  }
  const auto a = _0[{_, ~p}];
  const auto b = _0[{~p, ~p + ~q + 1}];
  _0 = _0[{~p + ~q + 1, _}];
  return {a, b};
}

}  // namespace sfc::fmt
